module klang.编译.输出工具.输出工具_;
import 全局;
import std.functional: ·fd = toDelegate;
import klang.编译.类型.枚举值.枚举值_: TK, SK, 字符_;
import klang.编译.常量值.常量值_: 获取SK关键字文本;
import klang.编译.类型.类型_: 基础符号_ = 符号_, 行和列_, 注释范围_, 文本范围_, 源映射范围_, 编译选项基类_, OnEmitNode_, OnSubstituteNode_, RawSourceMap, TempFlags, EmitHint, 打印机_, 打印选项_, 打印助手_, 新行种类_, IEmitTextWriter, SourceMapGenerator, PipelinePhase, ListFormat;
import klang.编译.语法节点.节点_: 节点_, 节点数组_, 源文件_, 分离注释信息_, 基础节点_ = 节点_, 基础源文件_ = 源文件_, nodeIsSynthesized, positionIsSynthesized;
import klang.编译.核心.核心_: 最小, 整数_, 裁剪文本, 过滤, 是空白单行字符, 是换行类的, 是空白或换行, 创建数组, 词典_, 返回零值, 循环每个, 查找数组索引, 分割, 创建词典;
import klang.编译.扫描工具.扫描工具_: 跳过杂项, 获取指令, 计算行开始组, 获取行开始组, 计算位置的行和列, 获取位置的行和列, 获取前方注释范围组, 循环每个前方注释范围_2, 循环每个尾随注释范围_1, 循环每个尾随注释范围_2, createRange, rangeIsOnSingleLine, positionsAreOnSameLine, rangeEndPositionsAreOnSameLine, rangeStartPositionsAreOnSameLine, rangeEndIsOnSameLineAsRangeStart, getLinesBetweenRangeEndAndRangeStart, getLinesBetweenPositionAndNextNonWhitespaceCharacter, getLinesBetweenPositionAndPrecedingNonWhitespaceCharacter;
import klang.编译.路径.路径_: 文件扩展名是;
import klang.编译.系统.系统_: sys;
import klang.编译.输出节点.输出节点_: 合成注释_, 输出节点_, EmitFlags, getEmitFlags, getCommentRange, getOriginalNode_1, getStartsOnNewLine, getOrCreateEmitNode, getSyntheticLeadingComments, getSyntheticTrailingComments;
import klang.编译.输出注释.输出注释_: 初始输出注释环境, 恢复输出注释环境, emitSourcePos, skipSourceTrivia, setSourceMapSource, emitCommentsAfterNode, emitCommentsBeforeNode, emitBodyWithDetachedComments, emitLeadingCommentsOfPosition, emitTrailingCommentsOfPosition, siblingNodePositionsAreComparable, emitSourceMapsBeforeNode, emitSourceMapsAfterNode;
import klang.编译.转换.转换_: noEmitSubstitution, noEmitNotification;
alias 管道输出函数_ = void delegate(EmitHint, 节点_);
klang.编译.输出工具.输出工具_.EmitTextWriter _文本写;
dstring _新行;
dstring delegate(long) 获取关键字文本;
bool delegate(节点_) 节点是否输出注释;
bool delegate(节点_) 应停止注释输出;
void delegate(EmitHint, 节点_) pipelineEmitWithHintWorker;
节点数组_!(节点_) delegate(节点_) getContainingNodeArray;
dstring carriageReturnLineFeed = "\r\n"d;
dstring lineFeed = "\n"d;
OnEmitNode_ onEmitNode;
OnEmitNode_ onEmitNode2;
bool delegate(节点_) isEmitNotificationEnabled;
OnSubstituteNode_ substituteNode;
OnSubstituteNode_ substituteNode2;
void delegate(节点_) onBeforeEmitNode;
void delegate(节点_) onAfterEmitNode;
void delegate(节点数组_!(节点_)) onBeforeEmitNodeArray;
void delegate(节点数组_!(节点_)) onAfterEmitNodeArray;
void delegate(节点_) onBeforeEmitToken;
void delegate(节点_) onAfterEmitToken;
bool extendedDiagnostics;
dstring newLine;
词典_!(bool) bundledHelpers;
dstring[] nodeIdToGeneratedName; // 词典_ of generated names for specific nodes.
dstring[] autoGeneratedIdToGeneratedName; // 词典_ of generated names for temp and loop variables.
词典_!(dstring) generatedNames; // 词典_ of names generated by the NameGenerator.
TempFlags[] tempFlagsStack; // Stack of enclosing name generation scopes.
TempFlags tempFlags; // TempFlags for the current name generation scope.
词典_!(dstring)[] reservedNamesStack; // Stack of TempFlags reserved in enclosing name generation scopes.
词典_!(dstring) reservedNames; // TempFlags to reserve in nested name generation scopes.
long nextListElementPos; // See comment in `getLeadingLineTerminatorCount`.
IEmitTextWriter ownWriter; // Reusable `IEmitTextWriter` for basic printing.
void delegate(dstring) write;
bool isOwnFileEmit;
bool recordInternalSection;
long sourceFileTextPos = 0;
节点_ lastSubstitution;
bool preserveSourceNewlines;
打印选项_ 打印选项;
klang.编译.输出工具.输出工具_.打印机基础环境_ 基础环境;
节点_ lastNode;
static this() {
    bundledHelpers = new 词典_!(bool)();
    write = cast(void delegate(dstring))(·fd(&.writeBase));
}
class EmitTextWriter : IEmitTextWriter {
    dstring output;
    int indent;
    bool lineStart;
    long lineCount;
    long linePos;
    private bool _hasTrailingComment;
    dstring 新行;
    dstring[] indentStrings;
    this() { }
    this(dstring 新行) {
        this.indentStrings = [""d, "    "d, "        "d, "            "d, "                "d, "                    "d, "                        "d, "                            "d, "                                "d, "                                    "d, "                                        "d, "                                            "d];
        this.output = ""d;
        this.indent = 0;
        this.lineStart = true;
        this.lineCount = 0;
        this.linePos = 0;
        this._hasTrailingComment = false;
        this.新行 = 新行;
    }
    void updateLineCountAndPosFor(dstring s) {
        long[] lineStartsOfS = .computeLineStarts(s);
        if (lineStartsOfS.length > 1) {
            this.lineCount = this.lineCount + lineStartsOfS.length - 1;
            long index = lineStartsOfS.length - 1;
            this.linePos = this.output.length - s.length + lineStartsOfS[index];
            this.lineStart = (this.linePos - this.output.length) == 0;
        }
        else {
            this.lineStart = false;
        }
    }
    void writeText(dstring s) {
        if ((s !is ··null!(dstring)) && s != ""d) {
            if (this.lineStart) {
                s = this.getIndentString(this.indent) ~ s;
                this.lineStart = false;
            }
            this.output ~= s;
            this.updateLineCountAndPosFor(s);
        }
    }
    void write(dstring s) {
        if (s !is ··null!(dstring)) {
            this._hasTrailingComment = false;
        }
        this.writeText(s);
    }
    void writeComment(dstring s) {
        if (s !is ··null!(dstring)) {
            this._hasTrailingComment = true;
        }
        this.writeText(s);
    }
    void reset() {
        this.output = ""d;
        this.indent = 0;
        this.lineStart = true;
        this.lineCount = 0;
        this.linePos = 0;
        this._hasTrailingComment = false;
    }
    void rawWrite(dstring s) {
        if (s !is ··null!(dstring)) {
            this.output ~= s;
            this.updateLineCountAndPosFor(s);
            this._hasTrailingComment = false;
        }
    }
    void writeLiteral(dstring s) {
        if ((s !is ··null!(dstring)) && s.length > 0) {
            this.write(s);
        }
    }
    void writeLine(bool force = ··null!(bool)) {
        if (!this.lineStart || force) {
            this.output ~= this.新行;
            ++this.lineCount;
            this.linePos = this.output.length;
            this.lineStart = true;
            this._hasTrailingComment = false;
        }
    }
    long getTextPosWithWriteLine() {
        return this.lineStart ? this.output.length : (this.output.length + this.新行.length);
    }
    void increaseIndent() {
        ++this.indent;
    }
    void decreaseIndent() {
        --this.indent;
    }
    long getIndent() {
        return this.indent;
    }
    long getTextPos() {
        return this.output.length;
    }
    long getLine() {
        return this.lineCount;
    }
    long getColumn() {
        return this.lineStart ? this.indent * this.getIndentSize() : this.output.length - this.linePos;
    }
    dstring getText() {
        return this.output;
    }
    bool isAtStartOfLine() {
        return this.lineStart;
    }
    bool hasTrailingWhitespace() {
        return this.output.length != 0 && 是空白或换行(this.output[this.output.length - 1]);
    }
    void clear() {
        this.reset();
    }
    bool trackSymbol() {
        return false;
    }
    void writeSymbol(dstring s, 基础符号_ _) {
        this.write(s);
    }
    void writeKeyword(dstring s) {
        return this.write(s);
    }
    void writeOperator(dstring s) {
        return this.write(s);
    }
    void writeParameter(dstring s) {
        return this.write(s);
    }
    void writeProperty(dstring s) {
        return this.write(s);
    }
    void writePunctuation(dstring s) {
        return this.write(s);
    }
    void writeSpace(dstring s) {
        return this.write(s);
    }
    void writeStringLiteral(dstring s) {
        return this.write(s);
    }
    void writeTrailingSemicolon(dstring s) {
        return this.write(s);
    }
    void reportInaccessibleThisError() { }
    void reportPrivateInBaseOfClassExpression() { }
    void reportInaccessibleUniqueSymbolError() { }
    dstring getIndentString(long level) {
        dstring singleLevel = this.indentStrings[1];
        {
            for (size_t current = this.indentStrings.length; current <= level; ++current) {
                .追加!(dstring)(this.indentStrings, this.indentStrings[current - 1] ~ singleLevel);
            }
        }
        return this.indentStrings[level];
    }
    long getIndentSize() {
        return this.indentStrings[1].length;
    }
    bool hasTrailingComment() {
        return this._hasTrailingComment;
    }
}
class 打印机基础环境_ {
    TK 目标;
    dstring 单行注释头;
    dstring 多行注释头;
    dstring 多行注释尾;
    bool inlineSources;
    bool commentsDisabled;
    bool hasWrittenComment;
    long containerPos;
    long containerEnd;
    long declarationListContainerEnd;
    IEmitTextWriter writer;
    源文件_ currentSourceFile;
    long[] currentLineMap;
    dstring newLine;
    分离注释信息_[] detachedCommentsInfo;
    bool sourceMapsDisabled;
    源映射范围_ sourceMapSource;
    long sourceMapSourceIndex;
    SourceMapGenerator sourceMapGenerator;
    源映射范围_ mostRecentlyAddedSourceMapSource;
    long mostRecentlyAddedSourceMapSourceIndex;
    this() { }
    this(TK _目标, dstring _单行注释头, dstring _多行注释头, dstring _多行注释尾) {
        this.目标 = _目标;
        this.单行注释头 = _单行注释头;
        this.多行注释头 = _多行注释头;
        this.多行注释尾 = _多行注释尾;
        this.inlineSources = (打印选项.inlineSources);
        this.commentsDisabled = (打印选项.removeComments);
        this.hasWrittenComment = false;
        this.containerPos = -1;
        this.containerEnd = -1;
        this.declarationListContainerEnd = -1;
        this.writer = 返回零值!(IEmitTextWriter)();
        this.currentSourceFile = 返回零值!(源文件_)();
        this.currentLineMap = 返回零值!(long[])();
        this.newLine = .getNewLineCharacter(.打印选项);
        this.detachedCommentsInfo = 创建数组!(分离注释信息_)();
        this.sourceMapsDisabled = true;
        this.sourceMapSource = 返回零值!(源映射范围_)();
        this.sourceMapSourceIndex = -1;
        this.sourceMapGenerator = 返回零值!(SourceMapGenerator)();
        this.mostRecentlyAddedSourceMapSource = 返回零值!(源映射范围_)();
        this.mostRecentlyAddedSourceMapSourceIndex = -1;
    }
}
void 设置打印选项(打印选项_ _打印选项) {
    .打印选项 = _打印选项;
    .preserveSourceNewlines = (打印选项.preserveSourceNewlines);
}
void 设置基础环境(打印助手_ 打印助手, 打印机基础环境_ _基础环境, OnEmitNode_ noEmitNotification, OnSubstituteNode_ noEmitSubstitution, dstring delegate(long) _获取ISK关键字文本, bool delegate(节点_) _节点是否输出注释, bool delegate(节点_) _应停止注释输出, void delegate(EmitHint, 节点_) _pipelineEmitWithHintWorker, 节点数组_!(节点_) delegate(节点_) _getContainingNodeArray) {
    ._设置回调函数(打印助手, cast(OnEmitNode_)(noEmitNotification), cast(OnSubstituteNode_)(noEmitSubstitution));
    .基础环境 = _基础环境;
    .获取关键字文本 = cast(dstring delegate(long))(_获取ISK关键字文本);
    .节点是否输出注释 = cast(bool delegate(节点_))(_节点是否输出注释);
    .应停止注释输出 = cast(bool delegate(节点_))(_应停止注释输出);
    .getContainingNodeArray = cast(节点数组_!(节点_) delegate(节点_))(_getContainingNodeArray);
    .pipelineEmitWithHintWorker = cast(void delegate(EmitHint, 节点_))(_pipelineEmitWithHintWorker);
}
void _设置回调函数(打印助手_ 打印助手, OnEmitNode_ noEmitNotification, OnSubstituteNode_ noEmitSubstitution) {
    .onEmitNode2 = cast(OnEmitNode_)(noEmitNotification);
    .onEmitNode = cast(OnEmitNode_)(.onEmitNode2);
    if (打印助手.onEmitNode !is ··null!(void delegate(EmitHint, 节点_, void delegate(EmitHint, 节点_)))) {
        .onEmitNode = 打印助手.onEmitNode;
    }
    .isEmitNotificationEnabled = 打印助手.isEmitNotificationEnabled;
    .substituteNode2 = cast(OnSubstituteNode_)(noEmitSubstitution);
    .substituteNode = cast(OnSubstituteNode_)(.substituteNode2);
    if (打印助手.substituteNode !is ··null!(节点_ delegate(EmitHint, 节点_))) {
        .substituteNode = 打印助手.substituteNode;
    }
    .onBeforeEmitNode = 打印助手.onBeforeEmitNode;
    .onAfterEmitNode = 打印助手.onAfterEmitNode;
    .onBeforeEmitNodeArray = 打印助手.onBeforeEmitNodeArray;
    .onAfterEmitNodeArray = 打印助手.onAfterEmitNodeArray;
    .onBeforeEmitToken = 打印助手.onBeforeEmitToken;
    .onAfterEmitToken = 打印助手.onAfterEmitToken;
    .extendedDiagnostics = 打印选项.extendedDiagnostics;
    .newLine = .getNewLineCharacter(.打印选项);
    .bundledHelpers = new 词典_!(bool)();
    .recordInternalSection = 打印选项.recordInternalSection;
}
void setWriter(IEmitTextWriter _writer = ··null!(IEmitTextWriter), SourceMapGenerator _sourceMapGenerator = ··null!(SourceMapGenerator)) {
    基础环境.writer = _writer; // TODO: GH#18217
    基础环境.sourceMapGenerator = _sourceMapGenerator;
    基础环境.sourceMapsDisabled = (基础环境.writer is ··null!(IEmitTextWriter)) || (基础环境.sourceMapGenerator is ··null!(SourceMapGenerator));
    初始输出注释环境(.基础环境);
}
void delegate(dstring) getWrite() {
    return cast(void delegate(dstring))(.write);
}
void setWrite(void delegate(dstring) w) {
    .write = cast(void delegate(dstring))(w);
}
void writeBase(dstring s) {
    基础环境.writer.write(s);
}
IEmitTextWriter beginPrint() {
    if (.ownWriter !is ··null!(IEmitTextWriter)) {
        return .ownWriter;
    }
    else {
        .ownWriter = .创建文本写(.newLine);
        return .ownWriter;
    }
}
dstring endPrint() {
    dstring text = ownWriter.getText();
    ownWriter.clear();
    return text;
}
void print(EmitHint hint, 节点_ node, 源文件_ sourceFile = ··null!(源文件_)) {
    if ((sourceFile !is ··null!(源文件_)) && (sourceFile.内容 !is ··null!(dstring))) {
        .setSourceFile(sourceFile);
    }
    .pipelineEmit(hint, node);
}
节点_ pipelineEmit(EmitHint emitHint, 节点_ node) {
    节点_ savedLastNode = .lastNode;
    节点_ savedLastSubstitution = .lastSubstitution;
    .lastNode = node;
    .lastSubstitution = ··null!(节点_);
    管道输出函数_ pipelinePhase = .getPipelinePhase(PipelinePhase.Notification, emitHint, node);
    pipelinePhase(emitHint, node);
    assert(.lastNode == node, "节点变化了"c);
    节点_ substitute = .lastSubstitution;
    .lastNode = savedLastNode;
    .lastSubstitution = savedLastSubstitution;
    if (substitute !is ··null!(节点_)) {
        return substitute;
    }
    return node;
}
管道输出函数_ getPipelinePhase(PipelinePhase phase, EmitHint emitHint, 节点_ node) {
    switch (phase) {
        case PipelinePhase.Notification: {
            if (.onEmitNode != .onEmitNode2 && ((.isEmitNotificationEnabled is ··null!(bool delegate(节点_))) || .isEmitNotificationEnabled(node))) {
                return cast(管道输出函数_)(·fd(&.pipelineEmitWithNotification));
            }
        }
        // falls through
        case PipelinePhase.Substitution: {
            if (.substituteNode != .substituteNode2) {
                .lastSubstitution = .substituteNode(emitHint, node);
                节点_ 比较节点 = .lastSubstitution ? .lastSubstitution : node;
                if (比较节点 != node) {
                    return cast(管道输出函数_)(·fd(&.pipelineEmitWithSubstitution));
                }
            }
        }
        // falls through
        case PipelinePhase.Comments: {
            if (.shouldEmitComments(node)) {
                return cast(管道输出函数_)(·fd(&.pipelineEmitWithComments));
            }
        }
        // falls through
        case PipelinePhase.SourceMaps: {
            if (.shouldEmitSourceMaps(node)) {
                return cast(管道输出函数_)(·fd(&.pipelineEmitWithSourceMaps));
            }
        }
        case PipelinePhase.Emit: {
            return cast(管道输出函数_)(·fd(&.pipelineEmitWithHint));
        }
        default: {
            assert(false, "不可及"c);
            return 返回零值!(管道输出函数_)();
        }
    }
}
void pipelineEmitWithSourceMaps(EmitHint hint, 节点_ node) {
    管道输出函数_ pipelinePhase = .getNextPipelinePhase(PipelinePhase.SourceMaps, hint, node);
    emitSourceMapsBeforeNode(node);
    pipelinePhase(hint, node);
    emitSourceMapsAfterNode(node);
}
void pipelineEmitWithNotification(EmitHint hint, 节点_ node) {
    管道输出函数_ pipelinePhase = .getNextPipelinePhase(PipelinePhase.Notification, hint, node);
    .onEmitNode(hint, node, cast(void delegate(EmitHint, 节点_))(pipelinePhase));
}
void pipelineEmitWithSubstitution(EmitHint hint, 节点_ node) {
    管道输出函数_ pipelinePhase = .getNextPipelinePhase(PipelinePhase.Substitution, hint, node);
    node = .lastSubstitution ? .lastSubstitution : 返回零值!(节点_)();
    .lastSubstitution = 返回零值!(节点_)();
    pipelinePhase(hint, node);
}
void pipelineEmitWithComments(EmitHint hint, 节点_ node) {
    管道输出函数_ pipelinePhase = .getNextPipelinePhase(PipelinePhase.Comments, hint, node);
    long savedContainerPos = 基础环境.containerPos;
    long savedContainerEnd = 基础环境.containerEnd;
    long savedDeclarationListContainerEnd = 基础环境.declarationListContainerEnd;
    emitCommentsBeforeNode(node, cast(bool delegate(节点_))(.应停止注释输出));
    pipelinePhase(hint, node);
    emitCommentsAfterNode(node, savedContainerPos, savedContainerEnd, savedDeclarationListContainerEnd);
}
void beforeEmitNode(节点_ node) {
    if (.preserveSourceNewlines && (getEmitFlags(node) & EmitFlags.IgnoreSourceNewlines) != 0) {
        .preserveSourceNewlines = false;
    }
}
void afterEmitNode(bool savedPreserveSourceNewlines) {
    .preserveSourceNewlines = savedPreserveSourceNewlines;
}
void pipelineEmitWithHint(EmitHint hint, 节点_ node) {
    if (.onBeforeEmitNode !is ··null!(void delegate(节点_))) {
        .onBeforeEmitNode(node);
    }
    if (.preserveSourceNewlines) {
        bool savedPreserveSourceNewlines = .preserveSourceNewlines;
        .beforeEmitNode(node);
        .pipelineEmitWithHintWorker(hint, node);
        .afterEmitNode(savedPreserveSourceNewlines);
    }
    else {
        .pipelineEmitWithHintWorker(hint, node);
    }
    if (.onAfterEmitNode !is ··null!(void delegate(节点_))) {
        .onAfterEmitNode(node);
    }
}
管道输出函数_ getNextPipelinePhase(PipelinePhase currentPhase, EmitHint emitHint, 节点_ node) {
    return .getPipelinePhase(.获取下个管道(currentPhase), emitHint, node);
}
bool shouldEmitComments(节点_ node) {
    if (基础环境.commentsDisabled) {
        return .节点是否输出注释(node);
    }
    else {
        return ((node.输出节点) !is ··null!(输出节点_)) && (((node.输出节点.leadingComments) !is ··null!(合成注释_[])) || ((node.输出节点.trailingComments) !is ··null!(合成注释_[])));
    }
}
bool shouldEmitSourceMaps(节点_ node) {
    return !基础环境.sourceMapsDisabled && node.种类 != SK.源文件;
}
void setSourceFile(源文件_ sourceFile) {
    基础环境.currentSourceFile = sourceFile;
    基础环境.currentLineMap = 返回零值!(long[])();
    基础环境.detachedCommentsInfo = 返回零值!(分离注释信息_[])();
    setSourceMapSource((cast(源映射范围_)((cast(文本范围_)(sourceFile)))));
}
void 输出源文件(源文件_ n) {
    节点数组_!(节点_) statements = n.语句组;
    文本范围_ 范围 = createRange(-1, -1);
    if ((statements !is null) && (statements.原型 !is ··null!(节点_[]))) {
        范围.开始 = statements.开始;
        范围.结束 = statements.结束;
    }
    emitBodyWithDetachedComments(n, 范围, cast(void delegate(节点_))(·fd(&.emitSourceFileWorker)));
}
void emitSourceFileWorker(节点_ n) {
    节点数组_!(节点_) statements = (cast(基础源文件_)(n)).语句组;
    .emitList(n, statements, ListFormat.MultiLine);
}
void emit(节点_ node = ··null!(节点_)) {
    if (node is ··null!(节点_)) {
        return;
    }
    .pipelineEmit(EmitHint.Unspecified, node);
}
void emitList(节点_ parentNode = ··null!(节点_), 节点数组_!(节点_) children = ··null!(节点数组_!(节点_)), ListFormat format = ··null!(ListFormat), long start = ··null!(long), long count = ··null!(long)) {
    if ((count is ··null!(long)) || count == 0) {
        count = children ? children.length - start : 0;
    }
    .emitNodeList(cast(void delegate(节点_))(·fd(&.emit)), parentNode, children, format, start, count);
}
long emitSKWithComment(long sk, long 开始, void delegate(dstring) writer, 节点_ contextNode, bool indentLeading = ··null!(bool)) {
    节点_ node = .getParseTreeNode_1(contextNode);
    bool isSimilarNode = (node !is ··null!(节点_)) && node.目标种类 == contextNode.目标种类;
    long startPos = 开始;
    if (isSimilarNode && (基础环境.currentSourceFile !is ··null!(源文件_)) && ((基础环境.currentSourceFile.内容) !is ··null!(dstring))) {
        开始 = 跳过杂项(基础环境.currentSourceFile.内容, 开始);
    }
    if (isSimilarNode && contextNode.开始 != startPos) {
        bool needsIndent = indentLeading && (基础环境.currentSourceFile !is ··null!(源文件_)) && ((基础环境.currentSourceFile.内容) !is ··null!(dstring)) && !positionsAreOnSameLine(startPos, 开始, 基础环境.currentSourceFile);
        if (needsIndent) {
            .increaseIndent();
        }
        emitLeadingCommentsOfPosition(startPos);
        if (needsIndent) {
            .decreaseIndent();
        }
    }
    开始 = .writeSkText(sk, cast(void delegate(dstring))(writer), 开始);
    if (isSimilarNode && contextNode.结束 != 开始) {
        emitTrailingCommentsOfPosition(开始, /*prefixSpace*/ true, /*forceNoNewline*/ false);
    }
    return 开始;
}
long emitTokenWithComment(long token, long 开始, void delegate(dstring) writer, 节点_ contextNode, bool indentLeading = ··null!(bool)) {
    节点_ node = .getParseTreeNode_1(contextNode);
    bool isSimilarNode = (node !is ··null!(节点_)) && node.目标种类 == contextNode.目标种类;
    long startPos = 开始;
    if (isSimilarNode && (基础环境.currentSourceFile !is ··null!(源文件_)) && ((基础环境.currentSourceFile.内容) !is ··null!(dstring))) {
        开始 = 跳过杂项(基础环境.currentSourceFile.内容, 开始);
    }
    if (isSimilarNode && contextNode.开始 != startPos) {
        bool needsIndent = indentLeading && (基础环境.currentSourceFile !is ··null!(源文件_)) && ((基础环境.currentSourceFile.内容) !is ··null!(dstring)) && !positionsAreOnSameLine(startPos, 开始, 基础环境.currentSourceFile);
        if (needsIndent) {
            .increaseIndent();
        }
        emitLeadingCommentsOfPosition(startPos);
        if (needsIndent) {
            .decreaseIndent();
        }
    }
    开始 = .writeTokenText(token, cast(void delegate(dstring))(writer), 开始);
    if (isSimilarNode && contextNode.结束 != 开始) {
        emitTrailingCommentsOfPosition(开始, /*prefixSpace*/ true, /*forceNoNewline*/ false);
    }
    return 开始;
}
void emitNodeList(void delegate(节点_) emit, 节点_ parentNode = ··null!(节点_), 节点数组_!(节点_) children = ··null!(节点数组_!(节点_)), ListFormat format = ··null!(ListFormat), long start = 0, long count = 0) {
    bool isUndefined = (children is ··null!(节点数组_!(节点_)));
    if (isUndefined && (format & ListFormat.OptionalIfUndefined) != 0) {
        return;
    }
    bool isEmpty = (children is ··null!(节点数组_!(节点_))) || start >= children.length || count == 0;
    if (isEmpty && (format & ListFormat.OptionalIfEmpty) != 0) {
        if (.onBeforeEmitNodeArray !is ··null!(void delegate(节点数组_!(节点_)))) {
            .onBeforeEmitNodeArray(children);
        }
        if (.onAfterEmitNodeArray !is ··null!(void delegate(节点数组_!(节点_)))) {
            .onAfterEmitNodeArray(children);
        }
        return;
    }
    if ((format & ListFormat.BracketsMask) != 0) {
        .writePunctuation(.getOpeningBracket(format));
        if (isEmpty && ((children !is null) && (children.原型 !is ··null!(节点_[])))) {
            emitTrailingCommentsOfPosition(children.开始, /*prefixSpace*/ true); // Emit comments within empty bracketed lists
        }
    }
    if (.onBeforeEmitNodeArray !is ··null!(void delegate(节点数组_!(节点_)))) {
        .onBeforeEmitNodeArray(children);
    }
    if (isEmpty) {
        // Write a line terminator 如果 the parent node was multi-line
        if ((format & ListFormat.MultiLine) != 0 && !(.preserveSourceNewlines && ((parentNode is ··null!(节点_)) || (基础环境.currentSourceFile !is ··null!(源文件_)) && ((基础环境.currentSourceFile.内容) !is ··null!(dstring)) && rangeIsOnSingleLine(parentNode, 基础环境.currentSourceFile)))) {
            .writeLine();
        }
        else if ((format & ListFormat.SpaceBetweenBraces) != 0 && (format & ListFormat.NoSpaceIfEmpty) == 0) {
            .writeSpace();
        }
    }
    else {
        // Write the opening line terminator or leading whitespace.
        bool mayEmitInterveningComments = (format & ListFormat.NoInterveningComments) == 0;
        bool shouldEmitInterveningComments = mayEmitInterveningComments;
        long leadingLineTerminatorCount = .getLeadingLineTerminatorCount(parentNode, children, format); // TODO: GH#18217
        if (leadingLineTerminatorCount != 0) {
            .writeLine(leadingLineTerminatorCount);
            shouldEmitInterveningComments = false;
        }
        else if ((format & ListFormat.SpaceBetweenBraces) != 0) {
            .writeSpace();
        }
        // Increase the indent, 如果 requested.
        if ((format & ListFormat.Indented) != 0) {
            .increaseIndent();
        }
        // Emit each child.
        节点_ previousSibling;
        bool shouldDecreaseIndentAfterEmit = false;
        {
            for (int i = 0; i < count; ++i) {
                节点_ child = children[start + i];
                // Write the delimiter 如果 this is not the first node.
                if ((format & ListFormat.AsteriskDelimited) != 0) {
                    // always write JSDoc in the format "\n *"
                    .writeLine();
                    .writeDelimiter(format);
                }
                else if (previousSibling !is ··null!(节点_)) {
                    // i.e
                    //      函数 commentedParameters(
                    //          /* Parameter a */
                    //          a
                    //          /* End of parameter a */ -> this comment isn't considered to be trailing comment of parameter "a" due to newline
                    //          ,
                    if ((format & ListFormat.DelimitersMask) != 0 && previousSibling.结束 != (parentNode ? parentNode.结束 : -1)) {
                        emitLeadingCommentsOfPosition(previousSibling.结束);
                    }
                    .writeDelimiter(format);
                    // Write either a line terminator or whitespace to separate the elements.
                    long separatingLineTerminatorCount = .getSeparatingLineTerminatorCount(previousSibling, child, format);
                    if (separatingLineTerminatorCount > 0) {
                        // If a synthesized node in a single-line list starts on a new
                        // line, we should increase the indent.
                        if ((format & (ListFormat.LinesMask | ListFormat.Indented)) == ListFormat.SingleLine) {
                            .increaseIndent();
                            shouldDecreaseIndentAfterEmit = true;
                        }
                        .writeLine(separatingLineTerminatorCount);
                        shouldEmitInterveningComments = false;
                    }
                    else if ((previousSibling !is ··null!(节点_)) && (format & ListFormat.SpaceBetweenSiblings) != 0) {
                        .writeSpace();
                    }
                }
                if (shouldEmitInterveningComments) {
                    文本范围_ commentRange = getCommentRange(child);
                    emitTrailingCommentsOfPosition(commentRange.开始);
                }
                else {
                    shouldEmitInterveningComments = mayEmitInterveningComments;
                }
                .nextListElementPos = child.开始;
                emit(child);
                if (shouldDecreaseIndentAfterEmit) {
                    .decreaseIndent();
                    shouldDecreaseIndentAfterEmit = false;
                }
                previousSibling = child;
            }
        }
        // Write a trailing comma, 如果 requested.
        EmitFlags emitFlags = previousSibling ? getEmitFlags(previousSibling) : EmitFlags.None;
        bool skipTrailingComments = 基础环境.commentsDisabled || (emitFlags & EmitFlags.NoTrailingComments) != 0;
        bool hasTrailingComma = (children !is null) && (children.原型 !is ··null!(节点_[])) && children.有尾随逗号 && (format & ListFormat.AllowTrailingComma) != 0 && (format & ListFormat.CommaDelimited) != 0;
        if (hasTrailingComma) {
            if ((previousSibling !is ··null!(节点_)) && !skipTrailingComments) {
                .emitSKWithComment(SK.逗号, previousSibling.结束, cast(void delegate(dstring))(·fd(&.writePunctuation)), previousSibling);
            }
            else {
                .writePunctuation(","d);
            }
        }
        if ((previousSibling !is ··null!(节点_)) && (parentNode ? parentNode.结束 : -1) != previousSibling.结束 && (format & ListFormat.DelimitersMask) != 0 && !skipTrailingComments) {
            emitLeadingCommentsOfPosition(hasTrailingComma && (children.结束 !is ··null!(long)) ? children.结束 : previousSibling.结束);
        }
        // Decrease the indent, 如果 requested.
        if ((format & ListFormat.Indented) != 0) {
            .decreaseIndent();
        }
        // Write the closing line terminator or closing whitespace.
        long closingLineTerminatorCount = .getClosingLineTerminatorCount(parentNode, children, format);
        if (closingLineTerminatorCount != 0) {
            .writeLine(closingLineTerminatorCount);
        }
        else if ((format & (ListFormat.SpaceAfterList | ListFormat.SpaceBetweenBraces)) != 0) {
            .writeSpace();
        }
    }
    if (.onAfterEmitNodeArray !is ··null!(void delegate(节点数组_!(节点_)))) {
        .onAfterEmitNodeArray(children);
    }
    if ((format & ListFormat.BracketsMask) != 0) {
        if (isEmpty && ((children !is null) && (children.原型 !is ··null!(节点_[])))) {
            emitLeadingCommentsOfPosition(children.结束); // Emit leading comments within empty lists
        }
        .writePunctuation(.getClosingBracket(format));
    }
}
void writeDelimiter(ListFormat format) {
    long f = (cast(整数_)(format & ListFormat.DelimitersMask));
    if (f == ListFormat.BarDelimited) {
        .writeSpace();
        .writePunctuation("|"d);
        return;
    }
    if (f == ListFormat.AmpersandDelimited) {
        .writeSpace();
        .writePunctuation("&"d);
        return;
    }
    if (f == ListFormat.CommaDelimited) {
        .writePunctuation(","d);
        return;
    }
    if (f == ListFormat.AsteriskDelimited) {
        .writeSpace();
        .writePunctuation("*"d);
        .writeSpace();
        return;
    }
    if (f == ListFormat.空白_) {
        .writeSpace();
        return;
    }
    return;
}
long writeToken(long token, long 开始, void delegate(dstring) writer, 节点_ contextNode = ··null!(节点_)) {
    return !基础环境.sourceMapsDisabled ? .emitTokenWithSourceMap(contextNode, token, cast(void delegate(dstring))(writer), 开始, cast(long delegate(long, void delegate(dstring), long))(·fd(&.writeTokenText))) : .writeTokenText(token, cast(void delegate(dstring))(writer), 开始);
}
void writeTokenNode(节点_ node, void delegate(dstring) writer) {
    if (.onBeforeEmitToken !is ··null!(void delegate(节点_))) {
        .onBeforeEmitToken(node);
    }
    writer(.获取关键字文本(node.目标种类));
    if (.onAfterEmitToken !is ··null!(void delegate(节点_))) {
        .onAfterEmitToken(node);
    }
}
long writeSkText(long token, void delegate(dstring) writer, long 开始) {
    dstring tokenString = 获取SK关键字文本(token);
    writer(tokenString);
    return 开始 < 0 ? 开始 : 开始 + tokenString.length;
}
long writeTokenText(long token, void delegate(dstring) writer, long 开始) {
    dstring tokenString = .获取关键字文本(token);
    writer(tokenString);
    return 开始 < 0 ? 开始 : 开始 + tokenString.length;
}
void writeLineOrSpace(节点_ parentNode, 节点_ prevChildNode, 节点_ nextChildNode) {
    if ((getEmitFlags(parentNode) & EmitFlags.SingleLine) != 0) {
        .writeSpace();
    }
    else if (.preserveSourceNewlines) {
        long lines = .getLinesBetweenNodes(parentNode, prevChildNode, nextChildNode);
        if (lines != 0) {
            .writeLine(lines);
        }
        else {
            .writeSpace();
        }
    }
    else {
        .writeLine();
    }
}
int guessIndentation(dstring[] lines) {
    int indentation = 1073741823;
    foreach (dstring line; lines) {
        if (line.length == 0) {
            continue;
        }
        int i = 0;
        for (; i < line.length && i < indentation; ++i) {
            if (!是空白或换行(line[i])) {
                break;
            }
        }
        if (i < indentation) {
            indentation = i;
        }
        if (indentation == 0) {
            return 0;
        }
    }
    return indentation == 1073741823 ? -1 : indentation;
}
void writeLines(dstring text) {
    dstring[] lines = 分割(text, ["\r\n"d, "\n"d, "\r"d]);
    int indentation = .guessIndentation(lines);
    foreach (dstring lineText; lines) {
        dstring line = indentation != -1 ? lineText[indentation .. $] : lineText;
        if (line.length != 0) {
            .writeLine();
            .write(line);
        }
    }
}
void writeLinesAndIndent(long lineCount, bool writeSpaceIfNotIndenting) {
    if (lineCount != 0) {
        .increaseIndent();
        .writeLine(lineCount);
    }
    else if (writeSpaceIfNotIndenting) {
        .writeSpace();
    }
}
// Helper 函数 to decrease the indent 如果 we previously indented.  Allows multiple
// previous indent values to be considered at a time.  This also allows caller to just
// call this once, passing in all their appropriate indent values, instead 属于 needing
// to call this helper 函数 multiple times.
void decreaseIndentIf(bool value1, long value2 = ··null!(long)) {
    if (value1) {
        .decreaseIndent();
    }
    if (value2 !is ··null!(long)) {
        .decreaseIndent();
    }
}
/**
* Emits a token of a node with possible leading and trailing source maps.
*
* @param node The node containing the token.
* @param token The token to emit.
* @param tokenStartPos The start pos of the token.
* @param emitCallback The callback used to emit the token.
*/
long emitTokenWithSourceMap(节点_ node = ··null!(节点_), long token = ··null!(long), void delegate(dstring) writer = ··null!(void delegate(dstring)), long tokenPos = ··null!(long), long delegate(long, void delegate(dstring), long) emitCallback = ··null!(long delegate(long, void delegate(dstring), long))) {
    if (基础环境.sourceMapsDisabled) {
        return emitCallback(token, cast(void delegate(dstring))(writer), tokenPos);
    }
    输出节点_ emitNode;
    if (node !is ··null!(节点_)) {
        emitNode = node.输出节点;
    }
    EmitFlags emitFlags = EmitFlags.None;
    if (emitNode !is ··null!(输出节点_)) {
        emitFlags = emitNode.标志;
    }
    源映射范围_ range;
    if ((emitNode !is ··null!(输出节点_)) && (emitNode.tokenSourceMapRanges !is ··null!(源映射范围_[])) && emitNode.tokenSourceMapRanges.length > token) {
        range = emitNode.tokenSourceMapRanges[token];
    }
    源文件_ source;
    if ((range !is ··null!(源映射范围_)) && (range.source !is ··null!(文本范围_))) {
        source = (cast(基础源文件_)(range.source));
    }
    else if (基础环境.sourceMapSource !is ··null!(源映射范围_)) {
        source = (cast(基础源文件_)((cast(文本范围_)(基础环境.sourceMapSource))));
    }
    if (source !is ··null!(源文件_)) {
        tokenPos = skipSourceTrivia(source, range ? range.开始 : tokenPos);
    }
    if ((emitFlags & EmitFlags.NoTokenLeadingSourceMaps) == 0 && tokenPos >= 0 && (source !is ··null!(源文件_))) {
        emitSourcePos(source, tokenPos);
    }
    tokenPos = emitCallback(token, cast(void delegate(dstring))(writer), tokenPos);
    if (range !is ··null!(源映射范围_)) {
        tokenPos = range.结束;
    }
    if ((emitFlags & EmitFlags.NoTokenTrailingSourceMaps) == 0 && tokenPos >= 0 && (source !is ··null!(源文件_))) {
        emitSourcePos(source, tokenPos);
    }
    return tokenPos;
}
long getLeadingLineTerminatorCount(节点_ parentNode = ··null!(节点_), 节点_[] children = ··null!(节点_[]), ListFormat format = ··null!(ListFormat)) {
    if ((format & ListFormat.PreserveLines) != 0 || .preserveSourceNewlines) {
        if ((format & ListFormat.PreferNewLine) != 0) {
            return 1;
        }
        节点_ firstChild = children[0];
        if (firstChild is ··null!(节点_)) {
            return (parentNode is ··null!(节点_)) || (基础环境.currentSourceFile !is ··null!(源文件_)) && rangeIsOnSingleLine(parentNode, 基础环境.currentSourceFile) ? 0 : 1;
        }
        if (firstChild.开始 == .nextListElementPos) {
            return 0;
        }
        if ((parentNode !is ··null!(节点_)) && !positionIsSynthesized(parentNode.开始) && !nodeIsSynthesized(firstChild) && ((firstChild.父节点 is ··null!(节点_)) || getOriginalNode_1(firstChild.父节点) == getOriginalNode_1(parentNode))) {
            if (.preserveSourceNewlines && (基础环境.currentSourceFile !is ··null!(源文件_))) {
                return .getEffectiveLines((bool includeComments) { return getLinesBetweenPositionAndPrecedingNonWhitespaceCharacter(firstChild.开始, parentNode.开始, 基础环境.currentSourceFile, includeComments); });
            }
            return (基础环境.currentSourceFile !is ··null!(源文件_)) && rangeStartPositionsAreOnSameLine(parentNode, firstChild, 基础环境.currentSourceFile) ? 0 : 1;
        }
        if (.synthesizedNodeStartsOnNewLine(firstChild, format)) {
            return 1;
        }
    }
    return (format & ListFormat.MultiLine) != 0 ? 1 : 0;
}
long getSeparatingLineTerminatorCount(节点_ previousNode = ··null!(节点_), 节点_ nextNode = ··null!(节点_), ListFormat format = ··null!(ListFormat)) {
    if ((format & ListFormat.PreserveLines) != 0 || .preserveSourceNewlines) {
        if ((previousNode is ··null!(节点_)) || (nextNode is ··null!(节点_))) {
            return 0;
        }
        if (.preserveSourceNewlines && siblingNodePositionsAreComparable(previousNode, nextNode, cast(节点_[] delegate(节点_))(.getContainingNodeArray)) && (基础环境.currentSourceFile !is ··null!(源文件_))) {
            return .getEffectiveLines((bool includeComments) { return getLinesBetweenRangeEndAndRangeStart(previousNode, nextNode, 基础环境.currentSourceFile, includeComments); });
        }
        else if (!.preserveSourceNewlines && !nodeIsSynthesized(previousNode) && !nodeIsSynthesized(nextNode) && (基础环境.currentSourceFile !is ··null!(源文件_))) {
            return rangeEndIsOnSameLineAsRangeStart(previousNode, nextNode, 基础环境.currentSourceFile) ? 0 : 1;
        }
        else if (.synthesizedNodeStartsOnNewLine(previousNode, format) || .synthesizedNodeStartsOnNewLine(nextNode, format)) {
            return 1;
        }
    }
    else if (getStartsOnNewLine(nextNode)) {
        return 1;
    }
    return (format & ListFormat.MultiLine) != 0 ? 1 : 0;
}
long getClosingLineTerminatorCount(节点_ parentNode = ··null!(节点_), 节点数组_!(节点_) children = ··null!(节点数组_!(节点_)), ListFormat format = ··null!(ListFormat)) {
    if ((format & ListFormat.PreserveLines) != 0 || .preserveSourceNewlines) {
        if ((format & ListFormat.PreferNewLine) != 0) {
            return 1;
        }
        节点_ lastChild = children[children.length - 1];
        if (lastChild is ··null!(节点_)) {
            return (parentNode is ··null!(节点_)) || (基础环境.currentSourceFile !is ··null!(源文件_)) && rangeIsOnSingleLine(parentNode, 基础环境.currentSourceFile) ? 0 : 1;
        }
        if ((parentNode !is ··null!(节点_)) && !positionIsSynthesized(parentNode.开始) && !nodeIsSynthesized(lastChild) && ((lastChild.父节点 is ··null!(节点_)) || lastChild.父节点 == parentNode)) {
            if (.preserveSourceNewlines && (基础环境.currentSourceFile !is ··null!(源文件_))) {
                long 结束 = lastChild.结束;
                return .getEffectiveLines((bool includeComments) { return getLinesBetweenPositionAndNextNonWhitespaceCharacter(结束, parentNode.结束, 基础环境.currentSourceFile, includeComments); });
            }
            return (基础环境.currentSourceFile !is ··null!(源文件_)) && rangeEndPositionsAreOnSameLine(parentNode, lastChild, 基础环境.currentSourceFile) ? 0 : 1;
        }
        if (.synthesizedNodeStartsOnNewLine(lastChild, format)) {
            return 1;
        }
    }
    if ((format & ListFormat.MultiLine) != 0 && (format & ListFormat.NoTrailingNewLine) == 0) {
        return 1;
    }
    return 0;
}
long getEffectiveLines(long delegate(bool) getLineDifference) {
    assert(.preserveSourceNewlines, "断言错误"c);
    long lines = getLineDifference(/*includeComments*/ true);
    if (lines == 0) {
        return getLineDifference(/*includeComments*/ false);
    }
    return lines;
}
bool writeLineSeparatorsAndIndentBefore(节点_ node, 节点_ 父节点) {
    long leadingNewlines = 0;
    if (.preserveSourceNewlines) {
        leadingNewlines = .getLeadingLineTerminatorCount(父节点, [node], ListFormat.None);
    }
    if (leadingNewlines != 0) {
        .writeLinesAndIndent(leadingNewlines, /*writeLinesIfNotIndenting*/ false);
    }
    return leadingNewlines != 0;
}
void writeLineSeparatorsAfter(节点_ node, 节点_ 父节点) {
    long trailingNewlines = 0;
    if (.preserveSourceNewlines) {
        trailingNewlines = .getClosingLineTerminatorCount(父节点, new 节点数组_!(节点_)([node]), ListFormat.None);
    }
    if (trailingNewlines != 0) {
        .writeLine(trailingNewlines);
    }
}
bool synthesizedNodeStartsOnNewLine(节点_ node, ListFormat format) {
    if (nodeIsSynthesized(node)) {
        bool startsOnNewLine = getStartsOnNewLine(node);
        if (startsOnNewLine is ··null!(bool)) {
            return (format & ListFormat.PreferNewLine) != 0;
        }
        return startsOnNewLine;
    }
    return (format & ListFormat.PreferNewLine) != 0;
}
long getLinesBetweenNodes(节点_ 父节点, 节点_ node1, 节点_ node2) {
    if ((getEmitFlags(父节点) & EmitFlags.NoIndentation) != 0) {
        return 0;
    }
    // Always use a newline 循环 synthesized code 如果 the synthesizer desires it.
    if (getStartsOnNewLine(node2)) {
        return 1;
    }
    if (!nodeIsSynthesized(父节点) && !nodeIsSynthesized(node1) && !nodeIsSynthesized(node2)) {
        if (.preserveSourceNewlines && (基础环境.currentSourceFile !is ··null!(源文件_))) {
            return .getEffectiveLines((bool includeComments) { return getLinesBetweenRangeEndAndRangeStart(node1, node2, 基础环境.currentSourceFile, includeComments); });
        }
        if ((基础环境.currentSourceFile !is ··null!(源文件_)) && !rangeEndIsOnSameLineAsRangeStart(node1, node2, 基础环境.currentSourceFile)) {
            return 1;
        }
    }
    return 0;
}
dstring getOpeningBracket(ListFormat format) {
    ListFormat index = (format & ListFormat.BracketsMask);
    if (index == ListFormat.Braces) {
        return "{"d;
    }
    if (index == ListFormat.Parenthesis) {
        return "("d;
    }
    if (index == ListFormat.AngleBrackets) {
        return "<"d;
    }
    if (index == ListFormat.SquareBrackets) {
        return "["d;
    }
    return "{"d;
}
dstring getClosingBracket(ListFormat format) {
    ListFormat index = (format & ListFormat.BracketsMask);
    if (index == ListFormat.Braces) {
        return "}"d;
    }
    if (index == ListFormat.Parenthesis) {
        return ")"d;
    }
    if (index == ListFormat.AngleBrackets) {
        return ">"d;
    }
    if (index == ListFormat.SquareBrackets) {
        return "]"d;
    }
    return "}"d;
}
void writeLiteral(dstring s) {
    基础环境.writer.writeLiteral(s);
}
void writeStringLiteral(dstring s) {
    基础环境.writer.writeStringLiteral(s);
}
void writeSymbol(dstring s, 基础符号_ sym) {
    基础环境.writer.writeSymbol(s, sym);
}
void writePunctuation(dstring s) {
    基础环境.writer.writePunctuation(s);
}
void writeTrailingSemicolon() {
    基础环境.writer.writeTrailingSemicolon(";"d);
}
void writeKeyword(dstring s) {
    基础环境.writer.writeKeyword(s);
}
void writeOperator(dstring s) {
    基础环境.writer.writeOperator(s);
}
void writeParameter(dstring s) {
    基础环境.writer.writeParameter(s);
}
void writeComment(dstring s) {
    基础环境.writer.writeComment(s);
}
void writeSpace() {
    基础环境.writer.writeSpace(" "d);
}
void writeProperty(dstring s) {
    基础环境.writer.writeProperty(s);
}
void writeLine(long count = 1) {
    {
        for (int i = 0; i < count; ++i) {
            基础环境.writer.writeLine(i > 0);
        }
    }
}
void increaseIndent() {
    基础环境.writer.increaseIndent();
}
void decreaseIndent() {
    基础环境.writer.decreaseIndent();
}
dstring printNode(EmitHint hint, 节点_ node, 源文件_ sourceFile) {
    if (node.种类 == SK.源文件) {
        return .printFile((cast(基础源文件_)(node)));
    }
    .writeNode(hint, node, sourceFile, .beginPrint());
    return .endPrint();
}
dstring printFile(源文件_ sourceFile) {
    .writeFile(sourceFile, .beginPrint(), /*sourceMapEmitter*/ ··null!(SourceMapGenerator));
    return .endPrint();
}
dstring printList(ListFormat format, 节点数组_!(节点_) nodes, 源文件_ sourceFile) {
    .writeList(format, nodes, sourceFile, .beginPrint());
    return .endPrint();
}
void writeNode(EmitHint hint, 节点_ node, 源文件_ sourceFile = ··null!(源文件_), IEmitTextWriter output = ··null!(IEmitTextWriter)) {
    IEmitTextWriter previousWriter = 基础环境.writer;
    .setWriter(output, /*_sourceMapGenerator*/ ··null!(SourceMapGenerator));
    .print(hint, node, sourceFile);
    ._reset();
    基础环境.writer = previousWriter;
}
void writeFile(源文件_ sourceFile, IEmitTextWriter output, SourceMapGenerator sourceMapGenerator = ··null!(SourceMapGenerator)) {
    IEmitTextWriter previousWriter = 基础环境.writer;
    .setWriter(output, sourceMapGenerator);
    .emitShebangIfNeeded(sourceFile);
    .print(EmitHint.源文件_, (cast(基础节点_)(sourceFile)), sourceFile);
    ._reset();
    基础环境.writer = previousWriter;
}
bool emitShebangIfNeeded(源文件_ sourceFile) {
    if (sourceFile.种类 == SK.源文件) {
        dstring shebang = 获取指令(sourceFile.内容);
        if (shebang !is ··null!(dstring)) {
            .writeComment(shebang);
            .writeLine();
            return true;
        }
    }
    return false;
}
void writeList(ListFormat format, 节点数组_!(节点_) nodes, 源文件_ sourceFile = ··null!(源文件_), IEmitTextWriter output = ··null!(IEmitTextWriter)) {
    IEmitTextWriter previousWriter = 基础环境.writer;
    .setWriter(output, /*_sourceMapGenerator*/ ··null!(SourceMapGenerator));
    if ((sourceFile !is ··null!(源文件_)) && (sourceFile.内容 !is ··null!(dstring))) {
        .setSourceFile(sourceFile);
    }
    .emitList(··null!(节点_), nodes, format);
    ._reset();
    基础环境.writer = previousWriter;
}
void _reset() {
    .nodeIdToGeneratedName = [];
    .autoGeneratedIdToGeneratedName = [];
    .generatedNames = 创建词典!(dstring)();
    .tempFlagsStack = [];
    .tempFlags = TempFlags.Auto;
    .reservedNamesStack = [];
    基础环境.currentSourceFile = 返回零值!(源文件_)();
    基础环境.currentLineMap = 返回零值!(long[])();
    基础环境.detachedCommentsInfo = 返回零值!(分离注释信息_[])();
    .lastNode = ··null!(节点_);
    .lastSubstitution = ··null!(节点_);
    .setWriter(/*output*/ ··null!(IEmitTextWriter), /*_sourceMapGenerator*/ ··null!(SourceMapGenerator));
}
EmitTextWriter 创建文本写(dstring 新行) {
    if ((._文本写 is ··null!(EmitTextWriter)) || ._新行 != 新行) {
        ._文本写 = new EmitTextWriter(新行);
    }
    return ._文本写;
}
PipelinePhase 获取下个管道(PipelinePhase p) {
    switch (p) {
        case PipelinePhase.Notification: {
            return PipelinePhase.Substitution;
        }
        case PipelinePhase.Substitution: {
            return PipelinePhase.Comments;
        }
        case PipelinePhase.Comments: {
            return PipelinePhase.SourceMaps;
        }
        case PipelinePhase.SourceMaps: {
            return PipelinePhase.Emit;
        }
        default: {
            return PipelinePhase.Notification;
        }
    }
}
long[] computeLineStarts(dstring text) {
    long[] result = 创建数组!(long)();
    int pos = 0;
    int lineStart = 0;
    while(pos < text.length) {
        immutable(dchar) ch = text[pos];
        ++pos;
        switch (ch) {
            case 字符_.回车符: {
                if (text[pos] == 字符_.换行符) {
                    ++pos;
                }
            }
            // falls through
            case 字符_.换行符: {
                .追加!(long)(result, lineStart);
                lineStart = pos;
                break;
            }
            default: {
                if (ch > 字符_.最大Ascii字符 && 是换行类的(ch)) {
                    .追加!(long)(result, lineStart);
                    lineStart = pos;
                }
                break;
            }
        }
    }
    .追加!(long)(result, lineStart);
    return result;
}
dstring getNewLineCharacter(编译选项基类_ options, dstring delegate() getNewLine = ··null!(dstring delegate())) {
    dstring delegate(新行种类_) 内部处理;
    dstring 内部处理·func(新行种类_ k) {
        if (k != 新行种类_.无_) {
            switch (k) {
                case 新行种类_.CarriageReturnLineFeed: {
                    return .carriageReturnLineFeed;
                }
                case 新行种类_.LineFeed: {
                    return .lineFeed;
                }
                default: break;
            }
        }
        return getNewLine ? getNewLine() : sys ? sys.新行 : .carriageReturnLineFeed;
    }
    内部处理 = &内部处理·func;
    if (options.语言id == "IR打印选项"d) {
        打印选项_ 选项 = (cast(打印选项_)(options));
        return 内部处理(选项.newLine);
    }
    else {
        return .carriageReturnLineFeed;
    }
}
bool isParseTreeNode(节点_ node) {
    return (node.标志 & 64) == 0;
}
节点_ getParseTreeNode_2(节点_ node = ··null!(节点_), bool delegate(节点_) nodeTest = ··null!(bool delegate(节点_))) {
    if ((node is ··null!(节点_)) || .isParseTreeNode(node)) {
        return node;
    }
    node = node.原始节点;
    while(node !is ··null!(节点_)) {
        if (.isParseTreeNode(node)) {
            return (nodeTest is ··null!(bool delegate(节点_))) || nodeTest(node) ? node : ··null!(节点_);
        }
        node = node.原始节点;
    }
    return ··null!(节点_);
}
节点_ getParseTreeNode_1(节点_ node = ··null!(节点_)) {
    return .getParseTreeNode_2(node, (节点_ n) { return n !is ··null!(节点_); });
}
